package com.bolt.core.view.components;

import com.bolt.common.BoltConstants;
import com.bolt.common.collection.MapUtil;
import com.bolt.common.ognl.ExpressionUtil;
import com.bolt.common.ognl.OgnlCache;
import com.bolt.common.reflect.ObjectUtil;
import com.bolt.common.utils.StrUtil;
import com.bolt.core.view.templates.FreemarkerTemplateEngine;
import com.bolt.core.view.templates.Template;
import com.bolt.core.view.templates.TemplateRenderingContext;
import ognl.OgnlException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Writer;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;


public abstract class ComponentsBase implements UIBase {

    protected final Log logger = LogFactory.getLog(getClass());

    protected Map<String, Object> parameters;

    protected Map<String, Object> dynamicParameters = new HashMap<>();

    protected String id;

    protected String name;

    protected String template;

    protected String templateDir;

    protected String theme;

    protected FreemarkerTemplateEngine engine;

    public void setTemplateEngine(FreemarkerTemplateEngine en) {
        this.engine = en;
    }

    public FreemarkerTemplateEngine getTemplateEngine() {
        return this.engine;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return StringUtils.isEmpty(name) ? this.id : this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getTemplate() {
        return template;
    }

    public void setTemplate(String template) {
        this.template = template;
    }

    public String getTemplateDir() {
        return templateDir;
    }

    public String getTheme() {
        return theme;
    }

    public void setTemplateDir(String templateDir) {
        this.templateDir = templateDir;
    }

    public void setTheme(String theme) {
        this.theme = theme;
    }

    protected abstract String getDefaultTemplate();

    protected void evaluateValue(HttpServletRequest request) {
        try {
            Object formValue = request.getAttribute(Form.PAGECONTEXT_FORMVALUES);
            String valueExp = (String) parameters.get("value");
            Object value = null;
            if (ExpressionUtil.isExpression(valueExp) && null != formValue) {
                value = ExpressionUtil.parseText(valueExp, formValue);
            }

            if (null == value && null != formValue && StrUtil.isNotBlank(getName())) {
                try {
                    value = OgnlCache.getValue(getName(), formValue);
                    request.setAttribute(Form.FORM_UPDATESTATE, true);
                } catch (OgnlException ex) {
                }
            }
            // 再取转参
            if (null == value && StrUtil.isNotBlank(getName())) {
                value = request.getParameter(getName());
            }
            if (value instanceof Boolean) {
                value = String.valueOf(value);
            }
            if (ObjectUtil.isNotNull(value) && ObjectUtil.length(value) > 0) {
                request.setAttribute(BoltConstants.FORM_ITME_VALUE_ATTRIBUTE, value);
            }
        } catch (Exception e) {
            logger.error(e);
        }
    }

    public ComponentsBase() {
        parameters = new LinkedHashMap<>();
    }


    protected Template buildTemplateName(String template) {
        String templateDir = getTemplateDir();
        String theme = getTheme();
        return new Template(templateDir, theme, template);
    }

    protected void evaluateParams(HttpServletRequest req) {
        String templateDir = getTemplateDir();
        String theme = getTheme();

        addParameter("templateDir", templateDir);
        addParameter("theme", theme);
        addParameter("name", StrUtil.isBlank(this.getName()) ? id : this.getName());
        addParameter("id", escape(id));
        if (MapUtil.isNotEmpty(dynamicParameters)) {
            parameters.putAll(dynamicParameters);
        }

    }


    @Override
    public void start(HttpServletRequest req, HttpServletResponse res, Writer writer) {

    }

    @Override
    public void end(HttpServletRequest req, HttpServletResponse res, Writer writer) {
        try {
            evaluateParams(req);
            evaluateValue(req);
            mergeTemplate(req, res, writer, buildTemplateName(getDefaultTemplate()));
            dynamicParameters.clear();
        } catch (Exception e) {
            logger.error(e);
        }
    }

    protected void mergeTemplate(HttpServletRequest req, HttpServletResponse res, Writer writer, Template template) throws Exception {
        final TemplateRenderingContext templateContext = new TemplateRenderingContext(req, res, writer, this, template);
        engine.renderTemplate(templateContext);
    }


    public Map<String, Object> getParameters() {
        return parameters;
    }

    public void addAllParameters(Map<String, Object> params) {

        parameters.putAll(params);
    }

    public void addParameter(String key, Object value) {
        if (key != null) {
            Map<String, Object> params = getParameters();
            if (value == null) {
                params.remove(key);
            } else {
                params.put(key, value);
            }
        }
    }


    public void addDynamicParameters(String key, Object value) {
        dynamicParameters.put(key, value);
    }


    protected String escape(String name) {
        if (name != null) {
            return name.replaceAll("[\\/\\.\\[\\]]", "_");
        } else {
            return null;
        }
    }


    public Map<String, Object> getDynamicParameters() {
        return dynamicParameters;
    }

}
